<?php


namespace Maowenke\redis\ranking;


use Maowenke\redis\Other;

class MredisRanking
{
    use Other;
    protected static $defaultKey = 'mranking';
    /**添加元素多个
     * @param string $member 作为标识的字段名
     * @param string $score 作为分数的字段名
     * @param array $data 二维数组，每个元素必须具备$member字段和$score字段
     * @param string $key 键名
     * @return bool
     * @throws \Exception
     */
    public static function Adds(string $member,string $score,array $data=[],string $key='mranking'){
        self::setRedis();
        foreach ($data as $v){
            if(!empty($v[$member])&&!empty($v[$score])){
                self::Add($member,$score,$v,$key);
            }
        }
        return true;
    }

    /**添加元素一个
     * @param string $member 作为标识的字段名
     * @param string $score 作为分数的字段名
     * @param array $data 一维数组，元素必须具备$member字段和$score字段
     * @param string $key 键名
     * @return bool
     * @throws \Exception
     */
    public static function Add(string $member,string $score,array $data=[],string $key='mranking'){
        self::setRedis();
        if(!empty($data[$score])&&!empty($data[$member])){
            return self::$redis->zAdd($key,$data[$score],$data[$member]);
        }
        return false;
    }

    /**
     * 获取排行榜前$count位
     * @param int $count 获取长度
     * @param string $sort 排序方式ASC/DESC
     * @param bool $hasScore 是否需要分数
     * @param string $key 键名
     * @return array
     * @throws \Exception
     */
    public static function getRanking(int $count,string $sort="DESC",bool $hasScore=false,string $key="mranking"){
        self::setRedis();
        return self::getRange($count-1,0,$sort,$hasScore,$key);
    }

    /**
     * 获取用户的排行
     * @param string $member 用户标识
     * @param string $sort 排序方式ASC/DESC
     * @param string $key 键名
     * @return false|int
     * @throws \Exception
     */
    public static function getMemberRanking(string $member,string $sort="DESC",string $key="mranking"){
        self::setRedis();
        if($sort=="ASC"){
            $res =  self::$redis->zRank($key,$member);
        }else{
            $res = self::$redis->zRevRank($key,$member);
        }
        if(is_numeric($res)){
            $res += 1;
        }
        return $res;
    }

    /**
     * 获取用户附近的用户
     * @param string $member 用户标识
     * @param int $count 附近的几名
     * @param string $type 向上还是向下UP/DOW
     * @param string $sort 排序方式SDC/DESC
     * @param bool $hasScore 是否需要分数
     * @param string $key 键名
     * @return array
     * @throws \Exception
     */
    public static function getMemberRange(string $member,int $count,string $type="UP",string $sort="DESC",bool $hasScore=false,string $key="mranking"){
        $mysort = self::getMemberRanking($member,$sort,$key);
        $mysort-=1;
        if($type=="UP"){
            $res = self::getRange($mysort,$mysort-$count,$sort,$hasScore,$key);
            array_pop($res);
        }else{
            $res = self::getRange($mysort+$count,$mysort+1,$sort,$hasScore,$key);
            $res = array_splice($res,1);
        }
        return $res;
    }

    /**获取一组数据
     * @param int $end 结束下标
     * @param int $start 开始下标
     * @param string $sort 排序方式
     * @param bool $hasScore 是否显示分数
     * @param string $key 键名
     * @return array
     * @throws \Exception
     */
    protected static function getRange(int $end,int $start=0,string $sort="DESC",bool $hasScore=false,string $key="mranking"){
        self::setRedis();
        if($sort=="ASC"){
            return self::$redis->zRange($key,$start,$end,$hasScore);
        }
        return self::$redis->zRevRange($key,0,$end,$hasScore);
    }
}